package server;

import entity.Connector;
import entity.Context;
import entity.Host;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @author xing fang bin
 * @date 2021/8/11 0011 20:54
 * @description
 */

/**
 * 作业思路：
 * 1、改造tomcat的xml文件，将端口号和webapps的路径配置在里边
 * 2、新建两个测试项目demo1和demo2，将编译文件拷贝到webapps文件夹里
 * 3、编写实体类
 * 4、加载配置文件server.xml
 * 5、存储webapps文件夹里demo1和demo2的servlet
 * 6、启动MiniCat，按照路径去寻找相应的servlet
 */
public class BootStrap {
/*    private Connector connectors = new Connector();

    private Context context = new Context();
    private ClassLoader classLoader;
    private HashMap<String,HttpServlet> servletMap = new HashMap<>();*/


    private ClassLoader classLoader;

    private Host host = new Host();

    private List<Connector> connectors = new ArrayList<>();

    private HashMap<String,HttpServlet> servletMap = new HashMap<>();

    public void start() throws IOException {
        //加载解析server.xml
        loadServer();
        //启动connectors
        for (Connector connector : connectors) {
            connector.start();
        }
//        loadXML();

//        loadServlet();

        /**
         * MiniCat1.0版本
         * 需求：浏览器请求http://localhost:8080/，返回字符串到页面
         */
        /*ServerSocket serverSocket = new ServerSocket(connectors.getPort());
        System.out.println("------------>通过端口" + connectors.getPort() + "启动了MiniCat！");*/
        /*while (true) {
            Socket accept = serverSocket.accept();
            OutputStream outputStream = accept.getOutputStream();
            String bodyStr = "Hello MiniCat!";
            String response = HttpProtocolUtil.getHttpHeader200(bodyStr.getBytes().length) + bodyStr;
            outputStream.write(response.getBytes());
            serverSocket.close();
        }*/

        /**
         * MiniCat2.0版本
         * 需求：封装request和response对象，返回html静态资源
         */
        /*while (true) {
            Socket accept = serverSocket.accept();
            InputStream inputStream = accept.getInputStream();
            Request request = new Request(inputStream);
            Response response = new Response(accept.getOutputStream());
            response.outputHtml(request.getUrl());
            accept.close();
        }*/

        /**
         * MiniCat3.0版本
         * 需求，封装request和response对象，返回动态资源（servlet）
         */
        // 加载解析相关的配置
        /*while (true) {
            Socket accept = serverSocket.accept();
            InputStream inputStream = accept.getInputStream();
            Request request = new Request(inputStream);
            Response response = new Response(accept.getOutputStream());
            if (servletMap.get(request.getUrl()) == null) {
                response.outputHtml(request.getUrl());
            } else {
                HttpServlet httpServlet = servletMap.get(request.getUrl());
                httpServlet.service(request, response);
            }

            accept.close();
        }*/

        /**
         * MiniCat3.1版本
         * 需求，多线程处理不同操作（静态资源或者动态资源）
         * 不使用线程池
         */
        /*while (true) {
            Socket accept = serverSocket.accept();
            RequestProcessor requestProcessor = new RequestProcessor(accept, servletMap);
            requestProcessor.start();
        }*/

        /**
         * MiniCat3.2版本
         * 需求，多线程处理不同操作（静态资源或者动态资源）
         * 使用线程池
         */
        /*TimeUnit unit = TimeUnit.SECONDS;
        BlockingQueue workQueue = new ArrayBlockingQueue<>(50);
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 50, 100, unit, workQueue);
        while (true) {
            Socket accept = serverSocket.accept();
            RequestProcessor requestProcessor = new RequestProcessor(accept, servletMap);
            threadPoolExecutor.execute(requestProcessor);
        }*/

    }

    /*public void loadXML() {
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("web.xml");
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(resourceAsStream);
            Element element = document.getRootElement();
            List<Element> selectNodes = element.selectNodes("//Service");
            for (Element selectNode : selectNodes) {
                Element connector = (Element) selectNode.selectSingleNode("//Connector");
                connectors.setPort(Integer.parseInt(connector.attributeValue("port")));

                Element engine = (Element) connector.selectSingleNode("//Engine");
                List<Element> hostElement = engine.selectNodes("//Host");
                for (Element host : hostElement) {
                    connectors.setHostName(host.attributeValue("name"));
                    String appBase = host.attributeValue("appBase");
                    connectors.setAppBase(appBase);
                    File file = new File(appBase);
                    if (file.isDirectory()) {
                        String[] list = file.list();
                        for (String s : list) {
                            File webAppFiles = new File(appBase+s);
                            if (webAppFiles.isDirectory()) {
                                String filesName = webAppFiles.getName();
                                context.setWebName(filesName);
                                loadServlet(webAppFiles.toString());
                            }
                        }
                    }
                }
            }
        } catch (DocumentException | FileNotFoundException e) {
            e.printStackTrace();
        }
    }*/
    /**
     * 启动之前加载配置文件server.xml
     */
    private void loadServer(){
        InputStream inputStream= this.getClass().getClassLoader().getResourceAsStream("web.xml");
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(inputStream);
            Element rootElement = document.getRootElement();
            List<Element> nodes = rootElement.selectNodes("//Context");
            //戒心context标签封装context对象
            for (Element node : nodes) {
                String docbase = node.attributeValue("docBase");
                String path = node.attributeValue("path");
                Context context = new Context(docbase,path);
                host.getContexts().add(context);
            }
            servletMap=host.getServletMappings();
            System.out.println("servletMap=====>>>>>" + servletMap);
            //解析connctor标签并封装
            List<Element> connctnodes = rootElement.selectNodes("//Connector");
            for (Element connctnode : connctnodes) {
                String port = connctnode.attributeValue("port");
                Connector connector = new Connector(Integer.parseInt(port),  servletMap);
                connectors.add(connector);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /*private void loadServlet(String webPath) throws FileNotFoundException {
        FileInputStream fileInputStream = new FileInputStream(webPath + "\\web.xml");
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(fileInputStream);
            Element element = document.getRootElement();
            List<Element> selectNodes = element.selectNodes("//servlet");
            for (Element selectNode : selectNodes) {
                Element servletName = (Element) selectNode.selectSingleNode("servlet-name");
                String nameValue = servletName.getStringValue();
                Element servletClass = (Element) selectNode.selectSingleNode("servlet-class");
                String classValue = servletClass.getStringValue();
                String replaceClassValue = classValue.replace(".", "\\");
                // 根据servletName的值找到url-pattern
                Element servletMapping = (Element) element.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + nameValue + "']");
                String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue();
                MyClassLoader myClassLoader = new MyClassLoader(connectors.getAppBase(),"demo1/");
                classLoader = myClassLoader;
                servletMap.put(urlPattern, (HttpServlet) classLoader.loadClass(classValue).newInstance());
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }*/

    /*private void loadServlet() {
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("web.xml");
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(resourceAsStream);
            Element element = document.getRootElement();
            List<Element> selectNodes = element.selectNodes("//servlet");
            for (Element selectNode : selectNodes) {
                Element servletName = (Element) selectNode.selectSingleNode("servlet-name");
                String nameValue = servletName.getStringValue();
                Element servletClass = (Element) selectNode.selectSingleNode("servlet-class");
                String classValue = servletClass.getStringValue();

                // 根据servletName的值找到url-pattern
                Element servletMapping = (Element) element.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + nameValue + "']");
                String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue();
                servletMap.put(urlPattern, (HttpServlet) Class.forName(classValue).newInstance());
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }*/

    public static void main(String[] args) {
        BootStrap bootStrap = new BootStrap();
        try {
            bootStrap.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
